<?php

namespace App\Models;

use App\Models\ComModel;

/**
 * 文章模型
 */
class ModuleModel extends ComModel
{

    public $tablename;

    public function __construct(...$param)
    {
        parent::__construct();
        $this->table = 'module';
    }

    //新增和编辑全部数据时验证
    private function _validate($data, $id = 0)
    {
        if (!$data) {
            return ams_rt(1, '参数错误');
        }
        ams_clean_xss($data);
        if (!$data['name']) {
            return ams_rt(1, '模块名称必须填写');
        }
        $flag = $this->field_exitsts($this->table, 'name', $data['name'], $id);
        if ($flag) {
            return ams_rt(1, '模块已存在');
        }
        return ams_rt(0, 'ok', $data);
    }

    //安装
    public function install($dirname = '')
    {
        $dirname = $dirname ? ucfirst(esc($dirname)) : '';
        $dirname = ams_safe_replace($dirname);
        if (!$dirname) {
            return ams_rt(1, '模块不存在');
        } else if (!is_dir(APPSPATH . $dirname)) {
            return ams_rt(1, '模块不存在');
        } elseif (!is_file(APPSPATH . $dirname . '/Config/Version.php')) {
            return ams_rt(1, '版本文件不存在');
        }

        $locks = WRITEPATH . 'module/' . ucfirst($dirname) . '.lock';
        if (is_file($locks)) {
            return ams_rt(1, '似乎已经安装过了');
        }

        if ($this->db->query('show tables LIKE "' . $this->db->getPrefix() . $dirname . '%"')->resultID->num_rows > 0) {
            return ams_rt(1, '存在表前缀存在:' . $this->db->getPrefix() . $dirname);
        }

        $set = require_once APPSPATH . $dirname . '/Config/Version.php';
        if (!isset($set['name']) || !$set['name'] || !isset($set['version'])) {
            return ams_rt(1, '版本文件错误');
        }

        $row = $this->getByDir($dirname);
        if ($row) {
            return ams_rt(1, '数据库中已存在,请先卸载');
        }

        //执行sql
        $sqlfile = APPSPATH . $dirname . '/Config/install.sql';
        if (is_file($sqlfile)) {
            // 导入表结构
            // $dbprefix = $this->db->getPrefix() . $dirname . '_';
            $dbprefix = $this->db->getPrefix();
            $this->_query(str_replace(['{dbprefix}'], [$dbprefix], file_get_contents($sqlfile)));
        }

        //安装锁定
        file_put_contents($locks, time());

        $this->db->table($this->table)->insert([
            'name' => $set['name'],
            'dirname' => strtolower($dirname),
            'status' => 1,
            'addtime' => time(),
            'version' => $set['version'],
        ]);
        $id = $this->db->insertID();
        if ($id) {
            $menu = new \App\Models\MenuModel();
            $menu->init_apps($dirname);
            $menu->init_apps($dirname, 'user');

            $rbac = new \App\Models\RbacModel();
            $rbac->iniRule($dirname);
            return ams_rt(0, '安装成功', $id);
        }
        return ams_rt(1, '安装失败');

    }

    //卸载
    public function uninstall($dirname = '')
    {
        $dirname = $dirname ? strtolower(esc($dirname)) : '';
        $dirname = ams_safe_replace($dirname);
        //数据库是否存在
        $dbprefix = $this->db->getPrefix();

        $sqlfile = APPSPATH . ucfirst($dirname) . '/Config/uninstall.sql';
        if (is_file($sqlfile)) {
            $this->_query(str_replace(['{dbprefix}'], [$dbprefix], file_get_contents($sqlfile)));
        }

        $locks = WRITEPATH . 'module/' . ucfirst($dirname) . '.lock';
        if (is_file($locks)) {
            @unlink($locks);
        }
        $this->db->table($this->table)->where('dirname', $dirname)->delete();

        //删除后台菜单
        $menu = new \App\Models\MenuModel();
        $menu->del_apps($dirname);

        $rbac = new \App\Models\RbacModel();
        $rbac->delRuleByMark('app-' . $dirname);

        return ams_rt(0, '卸载成功', $dirname);
    }

    //获取
    public function getById($id = 0)
    {
        $id = intval($id);
        $row = $this->db->table($this->table)->where('id', $id)->get()->getRowArray();
        if (isset($row) && $row['config']) {
            $row['config'] = json_decode($row['config'], true);
        }
        return $row;
    }

    public function getByDir($dirname = '')
    {
        $dirname = $dirname ? strtolower(esc($dirname)) : '';
        $dirname = ams_safe_replace($dirname);
        $row = $this->db->table($this->table)->where('dirname', $dirname)->get()->getRowArray();
        if (isset($row) && $row['config']) {
            $row['config'] = json_decode($row['config'], true);
        }
        return $row;
    }

    // 执行sql
    private function _query($sql)
    {
        if (!$sql) {
            return null;
        }
        $sql_data = explode(';SQL_CIMOK_EOL', trim(str_replace([PHP_EOL, chr(13), chr(10)], 'SQL_CIMOK_EOL', $sql)));
        foreach ($sql_data as $query) {
            if (!$query) {
                continue;
            }
            $ret = '';
            $queries = explode('SQL_CIMOK_EOL', trim($query));
            foreach ($queries as $query) {
                if ((isset($query[0]) && isset($query[1]) && $query[0] . $query[1] == '--') || (isset($query[0]) && $query[0] == '#')) {
                    continue;
                }
                $ret .= $query;
            }
            if (!$ret) {
                continue;
            }
            $this->db->query($ret);
        }
    }

    //获取模块列表
    public function getModuleList()
    {
        $dirs = get_module_dirs();
        $data = [];
        if ($dirs && is_array($dirs)) {
            foreach ($dirs as $v) {
                $file = APPSPATH . $v . '/Config/Version.php';
                $lock = WRITEPATH . 'module/' . ucfirst($v) . '.lock';
                if (is_file($file) && !is_file($lock)) {
                    $set = require_once APPSPATH . $v . '/Config/Version.php';
                    if (!isset($set['name']) || !$set['name'] || !isset($set['version'])) {
                        continue;
                    }
                    $set['dirname'] = $v;
                    $data[$v] = $set;
                }
            }
        }
        return $data;
    }

    public function edit($id, $data)
    {
        if (!$id) {
            return ams_rt(1, '参数错误');
        }
        $rt = $this->_validate($data, $id);
        if ($rt['code']) {
            return $rt;
        }
        $data = $rt['data'];

        $udata = [
            'name' => $data['name'],
            'description' => isset($data['description']) ? $data['description'] : '',
            'thumb' => isset($data['thumb']) ? $data['thumb'] : '',
            'status' => (isset($data['status']) && $data['status']) ? 1 : 0,
        ];

        $flag = $this->db->table($this->table)->where('id', $id)->update($udata);
        if ($flag) {
            //附件归属
            if (isset($data['thumb']) && $data['thumb']) {
                $related = $this->table . '-' . $id;
                $this->db->table('attachment')->where('id', intval($data['thumb']))->update(['related' => $related]);
            }
            return ams_rt(0, '操作成功', $id);
        }
        $msg = $this->db->error();
        return ams_rt(1, '操作失败:' . ($msg['message'] ?? ''));
    }

    public function get($id = 0)
    {
        $id = intval($id);
        $row = $this->db->table($this->table)->where('id', $id)->get()->getRowArray();
        if ($row && $row['config']) {
            $row['config'] = json_decode($row['config'], true);return $row;
        }
        return $row;
    }

    public function del($id)
    {
        if (!$id) {
            return ams_rt(1, '参数错误');
        }
        $row = $this->db->table($this->table)->where('id', $id)->get()->getRowArray();
        if (!$row) {
            return ams_rt(1, '数据不存在', []);
        }
        $this->db->table($this->table)->where('id', $id)->delete();
        return ams_rt(0, 'ok');
    }

    // 分页
    public function limit_page($page = 0, $size = 10, $total = 0, $param = [])
    {

        $page = max(1, (int) $page);
        $total = (int) $total;

        if ($param) {
            $param = esc($param);
        }

        if ($size > 0 && !$total) {
            $select = $this->db->table($this->table)->select('count(*) as total');
            $param = $this->_limit_page_where($select, $param);
            $query = $select->get();
            if (!$query) {
                log_message('error', '数据查询失败：' . $this->table);
                return [[], $total, $param];
            }
            $data = $query->getRowArray();
            $total = (int) $data['total'];
            $param['total'] = $total;
            unset($select);
            if (!$total) {
                return [[], $total, $param];
            }
        }

        $select = $this->db->table($this->table);
        $order = 'id desc';
        $param = $this->_limit_page_where($select, $param);
        $size > 0 && $select->limit($size, $size * ($page - 1));
        $query = $select->orderBy($order)->get();
        if (!$query) {
            log_message('error', '数据查询失败：' . $this->table);
            return [[], $total, $param];
        }
        $data = $query->getResultArray();
        if ($data) {
            foreach ($data as $k => $v) {
                $data[$k]['addtime_date'] = date('Y-m-d', $v['addtime']);
            }
        }
        $param['order'] = $order;
        $param['total'] = $total;

        return [$data, $total, $param];

    }

    /**
     * 条件查询
     *
     * @param    object    $select    查询对象
     * @param    intval    $where    是否搜索
     * @return    intval
     */
    protected function _limit_page_where(&$select, $param)
    {
        // 条件搜索
        if ($param) {
            if (isset($param['id']) && $param['id']) {
                $select->where('id', (int) $$param['id']);
            }
            if (isset($param['name']) && $param['name']) {
                $select->like('name', urldecode($param['name']));
            }
        }
        return $param;
    }

    public function switchStatus($id, $value)
    {
        if (!$id) {
            return ams_rt(1, '参数错误');
        }
        $row = $this->db->table($this->table)->select('id,name,status')->where('id', $id)->get()->getRowArray();
        if (!$row) {
            return ams_rt(1, '数据不存在');
        }
        $this->db->table($this->table)->where('id', $id)->update(['status' => $value]);
        return ams_rt(0, '操作成功', $row);
    }

    public function setdisplayorder($id, $displayorder)
    {
        return $this->displayorder($this->table, $id, $displayorder);
    }

}
